| 1 | [[PageOutline(2, Programming Languages)]] |
| 2 | |
| 3 | These snippets should be useful to read RAR archives with store compression (which means none compression is used). Feel free to edit/add source-codes if you have faster/better/new language implementation. |
| 4 | |
| 5 | Links: |
| 6 | * http://www.unrarlib.org/ |
| 7 | * http://www.rarlab.com/rar_add.htm |
| 8 | |
| 9 | == Python == |
| 10 | {{{ |
| 11 | #(c)Kamil Dzióbek turbos11(at)gmail.com |
| 12 | # BSD License |
| 13 | |
| 14 | from struct import * |
| 15 | |
| 16 | def getlastsplit(firsrarfile,x): |
| 17 | if firsrarfile[-3:]=='001': |
| 18 | return firsrarfile[:-3]+('%03d' %(x+1)) |
| 19 | if firsrarfile[-11:-6]=='.part': |
| 20 | return firsrarfile[0:-6]+('%02d' % (x+1))+firsrarfile[-4:] |
| 21 | if firsrarfile[-10:-5]=='.part': |
| 22 | return firsrarfile[0:-5]+('%1d' % (x+1))+firsrarfile[-4:] |
| 23 | return firsrarfile[0:-2]+('%02d' %(x-1) ) |
| 24 | |
| 25 | def addfilehash(name,hash,seek): |
| 26 | f=open(name, 'rb') |
| 27 | f.seek(seek) |
| 28 | for i in range(8192): |
| 29 | hash+=unpack('<q', f.read(8))[0] |
| 30 | hash =hash & 0xffffffffffffffff |
| 31 | return hash |
| 32 | |
| 33 | |
| 34 | def OpensubtitlesHashRar(firsrarfile): |
| 35 | """Hash file in rar split archive. -> (size,hash)""" |
| 36 | if not(firsrarfile.lower().endswith('.rar') | firsrarfile.endswith('.001')): |
| 37 | raise Exception('Bad file suffix. Only .rar and .001 support.') |
| 38 | if firsrarfile[-11:-6]=='.part': |
| 39 | firsrarfile=firsrarfile[0:-6]+'01'+firsrarfile[-4:] |
| 40 | f=open(firsrarfile, 'rb') |
| 41 | a=f.read(4) |
| 42 | if a!='Rar!': |
| 43 | raise Exception('ERROR: This is not rar file.') |
| 44 | seek=0 |
| 45 | for i in range(4): |
| 46 | f.seek(seek) |
| 47 | a=f.read(100) |
| 48 | type,flag,size=unpack( '<BHH', a[2:2+5]) |
| 49 | if 0x74==type: |
| 50 | if 0x30!=unpack( '<B', a[25:25+1])[0]: |
| 51 | raise Exception('Bad compression method! Work only for "store".') |
| 52 | s_partiizebodystart=seek+size |
| 53 | s_partiizebody,s_unpacksize=unpack( '<II', a[7:7+2*4]) |
| 54 | if (flag & 0x0100): |
| 55 | s_unpacksize=(unpack( '<I', a[36:36+4])[0] <<32 )+s_unpacksize |
| 56 | print 'Hash untested for files biger that 2gb. May work or may generate bad hash.' |
| 57 | lastrarfile=getlastsplit(firsrarfile,(s_unpacksize-1)/s_partiizebody) |
| 58 | hash=addfilehash(firsrarfile,s_unpacksize,s_partiizebodystart) |
| 59 | hash=addfilehash(lastrarfile,hash,(s_unpacksize%s_partiizebody)+s_partiizebodystart-65536) |
| 60 | return (s_unpacksize,"%016x" % hash ) |
| 61 | seek+=size |
| 62 | raise Exception('ERROR: Not Body part in rar file.') |
| 63 | |
| 64 | #example |
| 65 | firsrarsplitfile='I:\\test.rar' |
| 66 | size,hash=OpensubtitlesHashRar(firsrarsplitfile) |
| 67 | print 'use this valuse on opensubtiles.com\n\tsize is: %d\n\thash is: %s' % (size,hash) |
| 68 | }}} |